package com.southminority.ethnic.service.research.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.southminority.ethnic.common.exception.BusinessException;
import com.southminority.ethnic.common.result.PageResult;
import com.southminority.ethnic.mapper.research.PaperMapper;
import com.southminority.ethnic.pojo.Paper;
import com.southminority.ethnic.service.research.PaperService;
import com.southminority.ethnic.controller.research.vo.PaperVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 学术论文服务实现类.
 * <p>
 * 实现了 {@link PaperService} 接口，负责处理所有与学术论文相关的业务逻辑。
 * 包括数据查询、转换、增删改查等操作。
 * 
 * @author SouthMinority
 */
@Slf4j
@Service
@Transactional
public class PaperServiceImpl implements PaperService {

    private final PaperMapper paperMapper;

    public PaperServiceImpl(PaperMapper paperMapper) {
        this.paperMapper = paperMapper;
    }

    // =================================================================================
    // ==                             前端展示相关方法 (Public API)                     ==
    // =================================================================================

    @Override
    public PageResult<PaperVO> getPublishedPaperPage(Integer page, Integer size, String keyword, String paperType, Integer year) {
        Page<Paper> pageObj = new Page<>(page, size);
        QueryWrapper<Paper> wrapper = new QueryWrapper<>();

        wrapper.eq("status", 1);

        if (StringUtils.hasText(keyword)) {
            wrapper.and(qw -> qw.like("title", keyword)
                               .or().like("authors", keyword)
                               .or().like("keywords", keyword));
        }
        if (StringUtils.hasText(paperType)) {
            wrapper.eq("paper_type", paperType);
        }
        if (year != null) {
            wrapper.eq("publication_year", year);
        }

        wrapper.orderByDesc("publication_year").orderByDesc("create_time");

        IPage<Paper> pageResult = paperMapper.selectPage(pageObj, wrapper);
        List<PaperVO> voList = pageResult.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        
        return PageResult.<PaperVO>builder()
                .current(pageResult.getCurrent())
                .size(pageResult.getSize())
                .total(pageResult.getTotal())
                .pages(pageResult.getPages())
                .records(voList)
                .build();
    }

    @Override
    public PaperVO getPaperDetail(Long id) {
        Paper paper = paperMapper.selectById(id);
        if (paper == null || paper.getStatus() != 1) {
            throw new BusinessException("论文不存在或未发布");
        }
        return convertToVO(paper);
    }

    @Override
    public void increaseDownloadCount(Long id) {
        Paper paper = paperMapper.selectById(id);
        if (paper != null && paper.getStatus() == 1) {
            paper.setDownloadCount((paper.getDownloadCount() == null ? 0 : paper.getDownloadCount()) + 1);
            paper.setUpdateTime(LocalDateTime.now());
            paperMapper.updateById(paper);
        }
    }

    @Override
    public List<Integer> getPaperYears() {
        QueryWrapper<Paper> wrapper = new QueryWrapper<>();
        wrapper.select("DISTINCT publication_year")
               .eq("status", 1)
               .isNotNull("publication_year")
               .orderByDesc("publication_year");
        
        return paperMapper.selectList(wrapper).stream()
                          .map(Paper::getPublicationYear)
                          .collect(Collectors.toList());
    }

    @Override
    public List<String> getPaperTypes() {
        QueryWrapper<Paper> wrapper = new QueryWrapper<>();
        wrapper.select("DISTINCT paper_type")
               .eq("status", 1)
               .isNotNull("paper_type")
               .orderByAsc("paper_type");
        
        return paperMapper.selectList(wrapper).stream()
                          .map(Paper::getPaperType)
                          .filter(StringUtils::hasText)
                          .collect(Collectors.toList());
    }


    // =================================================================================
    // ==                             后台管理相关方法 (Admin API)                      ==
    // =================================================================================

    @Override
    public PageResult<PaperVO> getPaperPageForAdmin(Integer page, Integer size, String keyword, String paperType, Integer status) {
        Page<Paper> pageObj = new Page<>(page, size);
        QueryWrapper<Paper> wrapper = new QueryWrapper<>();
        
        if (StringUtils.hasText(keyword)) {
            wrapper.and(qw -> qw.like("title", keyword).or().like("authors", keyword));
        }
        if (StringUtils.hasText(paperType)) {
            wrapper.eq("paper_type", paperType);
        }
        if (status != null) {
            wrapper.eq("status", status);
        } else {
            wrapper.ne("status", -1);
        }
        
        wrapper.orderByDesc("publication_year").orderByDesc("create_time");
        
        IPage<Paper> pageResult = paperMapper.selectPage(pageObj, wrapper);
        List<PaperVO> voList = pageResult.getRecords().stream()
                                       .map(this::convertToVO)
                                       .collect(Collectors.toList());
        
        return PageResult.<PaperVO>builder()
                .current(pageResult.getCurrent())
                .size(pageResult.getSize())
                .total(pageResult.getTotal())
                .pages(pageResult.getPages())
                .records(voList)
                .build();
    }

    @Override
    public PaperVO getPaperDetailForAdmin(Long id) {
        Paper paper = paperMapper.selectById(id);
        if (paper == null) {
            throw new BusinessException("论文不存在");
        }
        return convertToVO(paper);
    }

    @Override
    public PaperVO createPaper(Paper paper) {
        if (paper == null) {
            throw new BusinessException("论文信息不能为空");
        }
        
        if (paper.getCitationCount() == null) paper.setCitationCount(0);
        if (paper.getDownloadCount() == null) paper.setDownloadCount(0);

        paper.setCreateTime(LocalDateTime.now());
        paper.setUpdateTime(LocalDateTime.now());
        
        paperMapper.insert(paper);
        return convertToVO(paper);
    }

    @Override
    public PaperVO updatePaper(Long id, Paper paper) {
        Paper existingPaper = paperMapper.selectById(id);
        if (existingPaper == null) {
            throw new BusinessException("论文不存在");
        }
        
        paper.setId(id);
        paper.setUpdateTime(LocalDateTime.now());
        
        paperMapper.updateById(paper);
        return convertToVO(paperMapper.selectById(id));
    }

    @Override
    public boolean deletePaper(Long id) {
        Paper paper = paperMapper.selectById(id);
        if (paper == null) {
            return true;
        }
        
        paper.setStatus(-1);
        paper.setUpdateTime(LocalDateTime.now());
        
        return paperMapper.updateById(paper) > 0;
    }

    @Override
    public boolean batchDeletePapers(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new BusinessException("ID列表不能为空");
        }
        
        List<Paper> paperList = paperMapper.selectBatchIds(ids);
        if (paperList.isEmpty()) {
            return true;
        }
        
        LocalDateTime now = LocalDateTime.now();
        for (Paper paper : paperList) {
            paper.setStatus(-1);
            paper.setUpdateTime(now);
            paperMapper.updateById(paper);
        }
        
        return true;
    }

    @Override
    public boolean updatePaperStatus(Long id, Integer status) {
        Paper paper = paperMapper.selectById(id);
        if (paper == null) {
            throw new BusinessException("论文不存在");
        }
        if (status == null || (status < -1 || status > 1)) {
            throw new BusinessException("无效的状态值");
        }
        
        paper.setStatus(status);
        paper.setUpdateTime(LocalDateTime.now());
        
        return paperMapper.updateById(paper) > 0;
    }

    // =================================================================================
    // ==                             私有辅助方法 (Private Helpers)                      ==
    // =================================================================================

    /**
     * 将 Paper POJO 转换为 PaperVO DTO.
     * <p>
     * 此方法负责将数据库实体对象转换为前端展示所需的视图对象，
     * 并进行必要的字段名映射。
     *
     * @param paper 数据库实体对象
     * @return 用于前端展示的视图对象
     */
    private PaperVO convertToVO(Paper paper) {
        if (paper == null) return null;
        
        PaperVO vo = new PaperVO();
        BeanUtils.copyProperties(paper, vo);

        // 特殊字段名映射
        vo.setPaperAbstract(paper.getAbstractText());
        
        return vo;
    }
} 
